import React, { createContext, useState, useContext, useCallback, useEffect } from 'react';
import { invoke } from '@tauri-apps/api/core';
import { logger } from '@/utils/logger';

export interface AuthState {
  isAuthenticated: boolean;
  isLoading: boolean;
  hasMasterPassword: boolean;
  error: string | null;
}

interface AuthContextType {
  // State
  isAuthenticated: boolean;
  isLoading: boolean;
  hasMasterPassword: boolean;
  error: string | null;
  
  // Actions
  checkMasterPassword: () => Promise<void>;
  setMasterPassword: (password: string) => Promise<boolean>;
  verifyMasterPassword: (password: string) => Promise<boolean>;
  logout: () => void;
  clearError: () => void;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

// Default auth state
const DEFAULT_AUTH_STATE: AuthState = {
  isAuthenticated: false,
  isLoading: true,
  hasMasterPassword: false,
  error: null,
};

export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [authState, setAuthState] = useState<AuthState>(DEFAULT_AUTH_STATE);

  const checkMasterPassword = useCallback(async () => {
    try {
      logger.info('[AuthContext] ========== CHECK MASTER PASSWORD START ==========');
      logger.info('[AuthContext] Current state before check', { hasMasterPassword: authState.hasMasterPassword, isLoading: authState.isLoading, isAuthenticated: authState.isAuthenticated });
      
      setAuthState(prev => ({ ...prev, isLoading: true, error: null }));
      logger.info('[AuthContext] Set isLoading to true');
      
      // Add retry logic to handle race condition with Tauri initialization
      let exists = false;
      let retries = 3;
      let lastError: any = null;
      
      while (retries > 0) {
        try {
          // Call Tauri command to check if master password exists
          exists = await invoke<boolean>('check_master_password_exists');
          logger.info('[AuthContext] Backend returned: ' + exists);
          break; // Success, exit retry loop
        } catch (error) {
          lastError = error;
          retries--;
          if (retries > 0) {
            logger.warn(`[AuthContext] Call failed, retrying... (${retries} attempts left)`);
            // Wait 100ms before retry
            await new Promise(resolve => setTimeout(resolve, 100));
          }
        }
      }
      
      if (retries === 0 && lastError) {
        throw lastError; // All retries failed
      }
      
      setAuthState(prev => {
        logger.info('[AuthContext] Updating state: hasMasterPassword = ' + exists + ', isLoading = false');
        logger.debug('[AuthContext] Previous state', prev);
        const newState = {
          ...prev,
          hasMasterPassword: exists,
          isLoading: false,
          error: null,
        };
        logger.debug('[AuthContext] New state', newState);
        return newState;
      });
      logger.info('[AuthContext] ========== CHECK MASTER PASSWORD END ==========');
    } catch (error) {
      logger.error('[AuthContext] ========== CHECK MASTER PASSWORD ERROR ==========');
      logger.error('[AuthContext] Failed to check master password: ' + error);
      // If there's an error, assume no master password exists
      setAuthState(prev => ({
        ...prev,
        hasMasterPassword: false,
        isLoading: false,
        error: null,
      }));
    }
  }, []);

  // Always check master password from backend on mount
  // Don't rely on localStorage because dev and prod may have different storage domains
  useEffect(() => {
    logger.info('[AuthContext] >>>>>> AuthContext mounted, initial state', authState);
    logger.info('[AuthContext] Calling checkMasterPassword()...');
    checkMasterPassword();
  }, [checkMasterPassword]);
  
  // Log all state changes
  useEffect(() => {
    logger.info('[AuthContext] ****** State changed', { isAuthenticated: authState.isAuthenticated, hasMasterPassword: authState.hasMasterPassword, isLoading: authState.isLoading });
  }, [authState]);

  const setMasterPassword = useCallback(async (password: string): Promise<boolean> => {
    try {
      setAuthState(prev => ({ ...prev, isLoading: true, error: null }));
      
      await invoke('set_master_password', { password });
      
      setAuthState(prev => ({
        ...prev,
        hasMasterPassword: true,
        isLoading: false,
        error: null,
      }));
      
      return true;
    } catch (error) {
      logger.error('Failed to set master password: ' + error);
      setAuthState(prev => ({
        ...prev,
        isLoading: false,
        error: error instanceof Error ? error.message : '设置主密码失败',
      }));
      return false;
    }
  }, []);

  const verifyMasterPassword = useCallback(async (password: string): Promise<boolean> => {
    try {
      setAuthState(prev => ({ ...prev, isLoading: true, error: null }));
      
      const isValid = await invoke<boolean>('verify_master_password', { password });
      
      if (isValid) {
        logger.info('Password verification successful, setting isAuthenticated to true');
        setAuthState(prev => ({
          ...prev,
          isAuthenticated: true,
          isLoading: false,
          error: null,
        }));
      } else {
        setAuthState(prev => ({
          ...prev,
          isLoading: false,
          error: '密码错误',
        }));
      }
      
      return isValid;
    } catch (error) {
      logger.error('Failed to verify master password: ' + error);
      setAuthState(prev => ({
        ...prev,
        isLoading: false,
        error: error instanceof Error ? error.message : '验证密码失败',
      }));
      return false;
    }
  }, []);

  const logout = useCallback(async () => {
    try {
      // Clear master password cache in backend
      await invoke('clear_master_password_cache');
    } catch (error) {
      logger.error('Failed to clear master password cache: ' + error);
    }

    setAuthState(prev => ({
      ...prev,
      isAuthenticated: false,
      error: null,
    }));
  }, []);

  const clearError = useCallback(() => {
    setAuthState(prev => ({ ...prev, error: null }));
  }, []);

  const value: AuthContextType = {
    // State
    isAuthenticated: authState.isAuthenticated,
    isLoading: authState.isLoading,
    hasMasterPassword: authState.hasMasterPassword,
    error: authState.error,
    
    // Actions
    checkMasterPassword,
    setMasterPassword,
    verifyMasterPassword,
    logout,
    clearError,
  };

  return (
    <AuthContext.Provider value={value}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};
